package services

import (
	"DetectiveMasterServer/model"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	crypter "github.com/heroicyang/wechat-crypter"
	"strconv"
	"strings"
	"time"
	"xwWechatPublic/middleware"
	"xwWechatPublic/middleware/app"
	"xwWechatPublic/models"
	"xwWechatPublic/utils/logging"
	"xwWechatPublic/utils/setting"
)

//获取微信access_token
func GetAccessToken() (access_token string, err error) {
	var result models.WxAccessTokenResponse
	base_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%v&secret=%v",
		setting.WechatSetting.AppID, setting.WechatSetting.AppSecret)
	logging.Debug("url[%v]", base_url)
	logging.Debug("begin ...")
	body, err := middleware.HttpRequest(base_url)
	err = json.Unmarshal(body, &result)
	if err != nil {
		logging.Error("ERROR[%v]", err.Error())
		return access_token, err
	}
	access_token = result.AccessToken
	return access_token, err
}

//获取用户UNIONID
func GetUserUnionID(openid string) (result models.WxUserInfoResponse, err error) {
	//var result models.WxUserInfoResponse
	logging.Info("准备获取UnionID ...")

	access_token, err := GetAccessToken()
	if err != nil {
		return result, err
	}
	base_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%v&openid=%v",
		access_token, openid)
	logging.Debug("url[%v]", base_url)
	body, err := middleware.HttpRequest(base_url)
	//logging.Debug("body[%v]", string(body))

	err = json.Unmarshal(body, &result)
	if err != nil {
		logging.Error("ERROR[%v]", err.Error())
		return result, err
	}
	//unionid = result.UnionId

	return result, err
}

//请求小程序接口创建房间
func CreateGameRoom(jparm models.WxCreateRoomReq) (resp models.WxCreateGameRoomResp, err error) {

	url := fmt.Sprintf("%v/wx.create", setting.RemoteServerSetting.Url)

	jsonStr, err := json.Marshal(&jparm)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return resp, err
	}
	//发送报文
	bodys, err := middleware.HttpPostJsonRequest(url, jsonStr)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return resp, err
	}

	//var resp models.WxCreateGameRoomResp
	err = json.Unmarshal(bodys, &resp)
	if err != nil {
		logging.Error("JSON报文解析失败")
		return resp, err
	}
	if resp.Err != 0 {
		logging.Error("获取剧本失败[%v]", resp.Msg)
		return resp, errors.New(resp.Msg)
	}
	//roomId = resp.Params.RoomId
	logging.Info("创建房间号是[%v]", resp.Params.RoomId)

	return resp, err
}

//请求小程序接口加入房间
func JoinGameRoom(jparm models.WxJoinRoomReq) (path string, err error) {

	url := fmt.Sprintf("%v/wx.join", setting.RemoteServerSetting.Url)

	jsonStr, err := json.Marshal(&jparm)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return path, err
	}
	//发送报文
	bodys, err := middleware.HttpPostJsonRequest(url, jsonStr)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return path, err
	}

	var resp models.WxJoinResp
	err = json.Unmarshal(bodys, &resp)
	if err != nil {
		logging.Error("JSON报文解析失败")
		return path, err
	}
	if resp.Err != 0 {
		logging.Error("获取剧本失败[%v]", resp.Msg)
		return path, errors.New(resp.Msg)
	}
	path = resp.Params.Path
	logging.Info("进入房间[%v]", path)

	return path, err
}

//请求小程序接口退出房间
func ExitGameRoom(jparm models.WxExitRoomReq) (err error) {

	url := fmt.Sprintf("%v/wx.exit", setting.RemoteServerSetting.Url)

	jsonStr, err := json.Marshal(&jparm)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return err
	}
	//发送报文
	bodys, err := middleware.HttpPostJsonRequest(url, jsonStr)
	if err != nil {
		logging.Error("JSON报文构造失败")
		return err
	}

	var resp models.WxExitResp
	err = json.Unmarshal(bodys, &resp)
	if err != nil {
		logging.Error("JSON报文解析失败")
		return err
	}
	if resp.Err != 0 {
		logging.Error("获取剧本失败[%v]", resp.Msg)
		//ERR_NOT_IN_ROOM
		if resp.Err == model.ERR_NOT_IN_ROOM {
			return errors.New("您未加入任何房间")
		}
		return errors.New(resp.Msg)
	}
	logging.Info("退出房间成功!")

	return err
}

//接收用户的消息
func PostRecvMsgHand(c *gin.Context) {
	appG := app.Gin{C: c}

	logging.Info("PostRecvMsgHand ...")

	//定义请求参数
	var jparm models.WxRecvMsgTextReq
	var content string //回复内容

	encrypt_type := c.Query("encrypt_type")
	logging.Info("加密方式[%v]", encrypt_type)
	//etype, bl := c.GetQuery(	"encrypt_type")
	//logging.Info("加密方式[%v] [%v]", etype, bl)

	//处理加密方式是 aes 的
	if encrypt_type == "aes" {
		var jmparm models.WxRecvMsgEncryptRequestBody
		err := c.ShouldBindXML(&jmparm)
		if err != nil {
			logging.Error("解析回调失败[%v]", err.Error())
			//rsp.ReturnCode = "FAIL"
			//rsp.ReturnMsg = "参数格式校验错误"
		}
		//logging.Info("参数[%v]", jparm)
		logging.Debug("开发者微信号[%v]", jmparm.ToUserName)
		logging.Info("密文[%v]", jmparm.Encrypt)
		logging.Info("获取请求报文成功!")

		//准备解析报文
		msgCrypter, _ := crypter.NewMessageCrypter(setting.WechatSetting.Token,
			setting.WechatSetting.EncodingAESKey,
			setting.WechatSetting.AppID)
		msgDecrypt, corpID, err := msgCrypter.Decrypt(jmparm.Encrypt)
		logging.Info("解密后的字符[%v]\n [%v]", string(msgDecrypt), corpID)

		//var tmp  models.TextRequestBody
		//err = xml.Unmarshal(msgDecrypt, &tmp)
		err = xml.Unmarshal(msgDecrypt, &jparm)
		if err != nil {
			logging.Error("XML报文解析失败!")
		}
		logging.Debug("XML解析[%v]", jparm)

	} else {
		err := c.ShouldBindXML(&jparm)
		if err != nil {
			logging.Error("解析回调失败[%v]", err.Error())
			//rsp.ReturnCode = "FAIL"
			//rsp.ReturnMsg = "参数格式校验错误"
		}
		logging.Info("参数[%v]", jparm)
	}

	logging.Debug("开发者微信号[%v]", jparm.ToUserName)
	logging.Debug("发送方APPID[%v]", jparm.FromUserName)
	logging.Debug("创建时间[%v]", jparm.CreateTime)
	logging.Debug("消息内容[%v]", jparm.Content)
	logging.Debug("消息ID[%v]", jparm.MsgId)

	result, _ := GetUserUnionID(jparm.FromUserName)
	logging.Info("unionid[%v] openid[%v]", result.UnionId, result.OpenId)

	//消息类型
	logging.Info("消息类型[%v]", jparm.MsgType)
	//处理文本消息
	if jparm.MsgType == "text" {

		//bl , err := regexp.Match("\\d+", []byte(jparm.Content))

		roomNo, err := strconv.Atoi(jparm.Content)
		if err == nil {
			logging.Info("房间号[%v],准备进入房间...", roomNo)
			var joinRoom models.WxJoinRoomReq
			joinRoom.RoomId = strconv.Itoa(roomNo)
			//joinRoom.OpenId = result.OpenId
			joinRoom.OpenId = result.UnionId //直接传unionid不用修改其他服务接口
			joinRoom.UnionId = result.UnionId
			path, err := JoinGameRoom(joinRoom)
			if err != nil {
				logging.Error("加入房间出错[%v]", err.Error())
				content = "加入房间出错!"
			} else {
				//content = "加入房间成功!"
				///pages/loadingnew/loadingnew?
				// is_create=1&script_id=103&unchoosed_num=1&open_id=541&room_id=351343
				content = fmt.Sprintf(`点击进入房间%v，<a data-miniprogram-appid='%v'
					data-miniprogram-path='%v'> 点击立即进入！</a>`,
					joinRoom.RoomId, setting.WechatSetting.SmallAppID, path)
			}
			logging.Info("content[%v]", content)
			var xRespParam models.WxRecvMsgTextResp
			xRespParam.MsgType = "text"
			xRespParam.ToUserName = jparm.FromUserName
			xRespParam.FromUserName = jparm.ToUserName
			xRespParam.Content = content
			xRespParam.CreateTime = time.Now().Unix()

			appG.ResponseXmlMessage(xRespParam)
			return
		}
		logging.Error("解析消息内容不为全数字[%v]", err.Error())

		//判断前缀是不是字符"创建"
		if strings.HasPrefix(jparm.Content, "创建") {

			var creatReq models.WxCreateRoomReq
			//creatReq.OpenId = result.OpenId
			creatReq.OpenId = result.UnionId
			creatReq.UnionId = result.UnionId
			creatReq.ScriptName = jparm.Content[len("创建"):]

			res, err := CreateGameRoom(creatReq)
			if err != nil {
				logging.Error("ERROR[%v]", err.Error())
				content = "输入有误，请重新输入"
				//content = err.Error()
			} else {
				content = fmt.Sprintf(`房间已建好，房间号是%v，<a data-miniprogram-appid='%v'
					data-miniprogram-path='%v'> 点击立即进入！</a>`,
					res.Params.RoomId, setting.WechatSetting.SmallAppID, res.Params.Path)
			}

		} else if jparm.Content == "退出房间" { //退出房间
			var exitReq models.WxExitRoomReq
			//exitReq.OpenId = result.OpenId
			exitReq.OpenId = result.UnionId
			exitReq.UnionId = result.UnionId

			err := ExitGameRoom(exitReq)
			if err != nil {
				logging.Error("ERROR[%v]", err.Error())
				//content = "退出房间出错，请稍后重试"
				content = err.Error()
			} else {
				content = fmt.Sprintf(`您已成功退出房间，如果想挑选剧本，<a data-miniprogram-appid='%v'
					data-miniprogram-path='pages/test/test'> 请点击查看所有剧本 </a>`,
					setting.WechatSetting.SmallAppID)
			}

		} else if jparm.Content == "图文" {

			var xRespParam models.WxRecvMsgNewsResp
			xRespParam.MsgType = "news"
			xRespParam.ToUserName = jparm.FromUserName
			xRespParam.FromUserName = jparm.ToUserName
			xRespParam.CreateTime = time.Now().Unix()

			//var cons 	[]models.ArticlesItem
			var con models.ArticlesItem
			con.Description = "第一条消息描述"
			con.Title = "第一条标题"
			con.PicUrl = "http://pic38.nipic.com/20140228/2457331_083845176000_2.jpg"
			con.Url = "http://www.baidu.com"

			//xRespParam.Articles = append(xRespParam.Articles, con)
			xRespParam.ArticlesItems = append(xRespParam.ArticlesItems, con)
			xRespParam.ArticleCount = len(xRespParam.ArticlesItems)

			//by, _ := xml.Marshal(xRespParam)
			//logging.Info("xml[%v]", string(by))

		} else {
			content = "随便输入的吧。如果想挑选剧本，请<a data-miniprogram-appid='wxa9cfedb5fad1edae' " +
				"data-miniprogram-path='pages/test/test'>点击查看所有剧本</a>"
		}

		var xRespParam models.WxRecvMsgTextResp
		xRespParam.MsgType = "text"
		xRespParam.ToUserName = jparm.FromUserName
		xRespParam.FromUserName = jparm.ToUserName
		xRespParam.Content = content
		xRespParam.CreateTime = time.Now().Unix()

		appG.ResponseXmlMessage(xRespParam)

	} else if jparm.MsgType == "image" {
		//图片消息

	} else if jparm.MsgType == "voice" {
		//语音消息

	} else if jparm.MsgType == "video" {
		//视频消息

	} else if jparm.MsgType == "shortvideo" {
		//小视频消息

	} else if jparm.MsgType == "location" {
		//地理位置消息

	} else if jparm.MsgType == "link" {
		//链接消息

	}

}
